﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace com.ReinforceLab.AlphaRexNxtStep
{
    class ApplicationContext : IDisposable, System.ComponentModel.INotifyPropertyChanged
    {
        #region Variables
        WiiBoardConnection wiiboard;
        AlphaRexModel alpha_rex;
        StringBuilder console_text;

        float prev_left_vector, prev_right_vector;
        int left_mortor_power, right_mortor_power;
        #endregion

        #region Properties
        public WiiBoardConnection WiiBoard {get{return wiiboard;}}
        public AlphaRexModel AlphaRex { get { return alpha_rex; } }

        public int LeftMortorPower { 
            get { return left_mortor_power; }
            private set { left_mortor_power = value; invokePropertyChanged("LeftMortorPower"); }
        }
        public int RightMortorPower { 
            get { return right_mortor_power; }
            private set { right_mortor_power = value; invokePropertyChanged("RightMortorPower"); }
        }

        public const String PN_ConsoleText = "ConsoleText";
        public String ConsoleText { get { return console_text.ToString(); } }
        #endregion

        #region Constructor
        public ApplicationContext()
        {
            initialize();
        }
        void initialize()
        {
            console_text = new StringBuilder();
            wiiboard  = new WiiBoardConnection(this);
            alpha_rex = new AlphaRexModel(this);

            prev_left_vector  = 0;
            prev_right_vector = 0;
            wiiboard.BoardStateUpdated += new EventHandler<EventArgs>(board_status_updated);
        }
        #endregion

        #region Private methods
        int vect_to_mortor(float vect)
        {
            if (Math.Abs(vect) < 0.1)
                return 0;

            return Math.Max(-100, Math.Min(100, (int)(vect * 80f)));

            /*
            // 0.3 以下 0
            // 0.3 - 0.7 70から90にマッピング
            // 0.7 以上 90
            float mag   = Math.Abs(vect);
            int power = 0;
            if (mag > 0.7)
            {
                power = 90;
            }
            else
            {
                if (mag > 0.3)
                {
                    power = (int)((mag - 0.3f) / (0.7f - 0.3f) * (90 - 70) + 70);
                }
            }

            if (vect < 0)
                power *= -1;

            return power;
             * */
        }
        void board_status_updated(Object sender, EventArgs e)
        { 
            // get vectors
            float top_left     = wiiboard.TopLeftWeight;
            float top_right    = wiiboard.TopRightWeight;
            float bottom_left  = wiiboard.BottomLeftWeight;
            float bottom_right = wiiboard.BottomRightWeight;


            //荷重が小さすぎるときは、モータはOff
            float left_weight = top_left + bottom_left;
            float right_weight = top_right + bottom_right;

            float left_vect  = 0;
            float right_vect = 0;
            
            if (left_weight > 4)
                left_vect = (top_left - bottom_left) / left_weight;
            if (right_weight > 4)
                right_vect = (top_right - bottom_right) / right_weight;


            left_mortor_power  = vect_to_mortor(left_vect);
            right_mortor_power = vect_to_mortor(right_vect);
            // 出力アップデート
            alpha_rex.Step(left_mortor_power, right_mortor_power);
            // 表示アップデート
            LeftMortorPower  = left_mortor_power;
            RightMortorPower = right_mortor_power;

            //System.Diagnostics.Debug.WriteLine(String.Format("left_vec:{0}, left_mortor:{1}", left_vect, LeftMortorPower));
        }
        #endregion

        #region Public methods
        public void WriteConsole(String line)
        {
            System.Diagnostics.Debug.WriteLine(line);
            console_text.AppendLine(line);
            invokePropertyChanged(PN_ConsoleText);
        }
        public void ClearConsole(String line)
        {
            console_text = new StringBuilder();            
            invokePropertyChanged(PN_ConsoleText);
        }
        #endregion

        #region IDisposable メンバ
        public void Dispose()
        {
            if (null != wiiboard)
            {
                wiiboard.Dispose();
                wiiboard = null;
            }            
        }
        #endregion

        #region INotifyPropertyChanged メンバ
        public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;
        void invokePropertyChanged(String name)
        {
            if (null != PropertyChanged)
                PropertyChanged.Invoke(this, new System.ComponentModel.PropertyChangedEventArgs(name));
        }
        #endregion
    }
}
